<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import * as echarts from 'echarts'

const props = defineProps({
  option: {
    type: Object,
    default: () => ({})
  },
  data: {
    type: Array,
    default: () => []
  },
  autoAction: {
    type: Boolean,
    default: false
  }
})
const chartDomRef = ref()
let chartInstance = null

const generateOption = () => {
  const {
    color,
    datasetDimensions,
    datasetSourceProduct,
    leftRight,
    topBottom,
    sort,
    labelPosition
  } = props.option

  const opt: any = {
    color: color ?? ['#5af', '#fa5'],
    tooltip: {
      trigger: 'item',
      textStyle: {
        color: 'var(--ec-text-color)'
      },
      backgroundColor: 'var(--ec-background-color)',
      borderColor: 'var(--ec-border-color)',
      formatter: (params) => `${params.name} ${params.data[datasetDimensions[0]]}`
    },
    dataset: {
      dimensions: ['product', ...datasetDimensions],
      source: props.data.map((data: any) => {
        data.product = data[datasetSourceProduct]
        return data
      })
    },
    series: []
  }

  const item: any = {
    type: 'funnel',
    sort: sort,
    left: `${leftRight[0]}%`,
    right: `${100 - leftRight[1]}%`,
    top: `${100 - topBottom[1]}%`,
    bottom: `${topBottom[0]}%`,
    minSize: '0%',
    maxSize: '100%',
    gap: 3,
    itemStyle: {
      borderWidth: 0
    },
    label: {
      show: labelPosition == 'none' ? false : true,
      position: labelPosition,
      formatter: (params) => `${params.name} ${params.data[datasetDimensions[0]]}`,
      textBorderColor: 'transparent',
      textBorderWidth: 0
    },
    emphasis: {
      label: {
        fontSize: 15
      }
    }
  }

  opt.series = new Array(datasetDimensions.length).fill(item)

  return opt
}

watch(
  props,
  () => {
    if (chartInstance) {
      chartInstance.clear()
      chartInstance.setOption(generateOption(), { notMerge: true })
    }
  },
  { deep: true }
)
// 轮流选择
let currentIndex = -1
let intervalAction = null
let actionDelay = 1000
let actionable = ref(true)

const action = function () {
  if (!actionable.value || !chartInstance) return

  let dataLen = props.data.length

  chartInstance.dispatchAction({
    type: 'downplay',
    seriesIndex: 0,
    dataIndex: currentIndex
  })

  const index = (currentIndex + 1) % dataLen
  currentIndex = Number.isNaN(index) ? -1 : index

  chartInstance.dispatchAction({
    type: 'highlight',
    seriesIndex: 0,
    dataIndex: currentIndex
  })
  chartInstance.dispatchAction({
    type: 'showTip',
    seriesIndex: 0,
    dataIndex: currentIndex
  })
}

watch(
  () => props.autoAction,
  (newVal) => {
    if (intervalAction) clearInterval(intervalAction)

    if (newVal) intervalAction = setInterval(action, actionDelay)
  },
  {
    immediate: true
  }
)
// 初始化
const initChart = () => {
  nextTick(() => {
    chartInstance = echarts.init(chartDomRef.value)
    chartInstance.setOption(generateOption())
  })
}

let resizeObserver
const chartResizeObserver = () => {
  resizeObserver = new window.ResizeObserver((entries) => chartInstance?.resize())
  resizeObserver.observe(chartDomRef.value)
}

onMounted(() => {
  initChart()
  chartResizeObserver()
})

onUnmounted(() => {
  chartInstance?.dispose()
  chartInstance = null
  if (resizeObserver) resizeObserver.disconnect()
})
</script>

<template>
  <div ref="chartDomRef" :style="{ width: '100%', height: '100%' }" @mouseover="actionable = false"
    @mouseout="actionable = true"></div>
</template>

<style scoped></style>
